package com.learn.spring.test;

import com.learn.spring.aop.AopDemo;
import com.learn.spring.aop.AopXmlDemo;
import com.learn.spring.config.AopSpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Case4 {

    /**
     * AOP(术语)
     * 1、连接点 : 类中那些方法可以被增强，那么就有几个链接点
     * 2、切入点 : 类中实际被增强的方法，就有几个切入点
     * 3、通知（增强) : 实际增强不分的代码就是通知：
     *   1） 前置通知
     *   2） 后置通知
     *   3） 环绕通知 在被增强的方法之前之后都执行，其实就是前置后置都会执行
     *   4） 异常通知 档被增强方法出现异常会通知
     *   5） 最终通知 不管出现什么状况都会执行的 finally
     * 4、切面 : 是个动作或者过程，把通知应用到切入点的过程就是切面。
     */

    /**
     * AOP操作〔准备）。
     * 1、Spring 框架一般都是基于 AspectJ 实现 AOP 操作
     * (1) 什么是 AspectJ
     *  * AspectJ 不是 Spring 组成部分，独立 AOP 框架，一般把 AspectJ 和 Spring 框架一起使用，进行 AOP 操作
     *
     * 2、基于 AspectJ 实现 AOP 操作
     * (1) 基于 xml 配置文件实现;
     * (2) 基于注解方式实现(使用);
     *
     * 3、在项目工程里面引入 AOP 相关依赖
     *   cglib
     *   aopalliance
     *   aspectj.weaver
     *   spring-aspects
     *
     * 4、切入点的表达式
     * (1) 切入点表达式作用:知道对哪个类里面的哪个方法进行增强
     * (2) 语法结构 : execution([权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]))
     *    [权限修饰符] 可以取 public private pro 等； * 可以代表全部匹配
     *   举例 1: 对 com.atguigu.dao.BookDao 类里面的 add 进行增强:
     *      execution(* com.atquiqu.dao.BookDao.add(..))
     *   举例 2: 对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强：
     *      execution(* com.atguigu.dao.BookDao.*(..))
     *   举例 3: 对com.atguigu.dao包里面所有类，类里面所有方法进行增强：
     *      execution(* com.atguigu.dao.*.*(..))
     */

    /**
     * 1. 创建目标类
     * 2. 创建增强行为代理类
     * 3. 开启配置
     * (1) 在 spring 配置文件中，开启注解扫描
     * (2) 使用注解创建 AopDemo 和 AopDemoProxy 对象
     * (3) 在增强行为代理类上面添加注解 @Aspect
     * (4) 在 spring 配置文件中开启生成代理对象
     */
    @Test
    public void test1() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans5.xml");
        AopDemo aopDemo = context.getBean("aopDemo", AopDemo.class);
        aopDemo.show();
    }

    /**
     * 实用完全注解方式开启AOP
     */
    @Test
    public void test2() {
        ApplicationContext context = new AnnotationConfigApplicationContext(AopSpringConfig.class);
        AopDemo aopDemo = context.getBean("aopDemo", AopDemo.class);
        aopDemo.show();
    }

    /**
     * 实用XML织入AOP
     */
    @Test
    public void test3() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans6.xml");
        AopXmlDemo aopXmlDemo = context.getBean("aopXmlDemo", AopXmlDemo.class);
        aopXmlDemo.show();
    }

}
